<template>
  <div>
    <!-- 顶部用户搜书和用户信息重置 -->
    <el-card style="height: 80px">
      <el-form :inline="true" class="search-form">
        <el-form-item label="用户名:">
          <el-input placeholder="搜索用户" v-model="keyword"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="default" @click="search">
            搜索
          </el-button>
          <el-button type="primary" size="default" @click="refresh">
            重制
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 用户信息展示 -->
    <el-card style="margin: 10px 0">
      <el-button
        type="primary"
        size="default"
        @click="addUser"
        v-has="`btn.User.add`"
      >
        添加用户
      </el-button>
      <el-button
        type="primary"
        size="default"
        @click="deleteSelectUser"
        :disabled="selectUserList.length > 0 ? false : true"
        v-has="`btn.User.remove`"
      >
        批量删除
      </el-button>
      <!-- 展示用户信息 -->
      <el-table
        border
        style="margin: 10px 0px"
        :data="userArr"
        @selection-change="selectChange"
      >
        <el-table-column type="selection" align="center"></el-table-column>
        <el-table-column
          label="#"
          align="center"
          type="index"
        ></el-table-column>
        <el-table-column label="ID" align="center" prop="id"></el-table-column>
        <el-table-column
          label="用户名字"
          align="center"
          prop="username"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="用户名称"
          align="center"
          prop="name"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="用户角色"
          align="center"
          prop="roleName"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="创建时间"
          align="center"
          prop="createTime"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="更新时间"
          align="center"
          prop="updateTime"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column label="操作" align="center" width="300px">
          <template #="{ row, $index }">
            <el-button
              type="primary"
              size="small"
              icon="User"
              @click="setRole(row)"
              v-has="`btn.User.assgin`"
            >
              分配角色
            </el-button>
            <el-button
              type="primary"
              size="small"
              icon="User"
              @click="updateUser(row)"
              v-has="`btn.User.update`"
            >
              编辑
            </el-button>
            <el-popconfirm
              :title="`你确定要删除${row.username}?`"
              width="260px"
              @confirm="deleteUser(row.id)"
            >
              <template #reference>
                <el-button
                  type="primary"
                  size="small"
                  icon="Delete"
                  v-has="`btn.User.remove`"
                >
                  删除
                </el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页器 -->
      <el-pagination
        v-model:current-page="pageNo"
        v-model:page-size="pageSize"
        :page-sizes="[5, 7, 9, 11]"
        :background="true"
        layout="prev, pager, next, jumper,->,sizes,total"
        :total="total"
        @current-change="getHasUser"
        @size-change="handler"
      />
    </el-card>
    <!-- 修改 | 添加用户信息的抽屉 -->
    <el-drawer v-model="drawer" @close="closeDrawer">
      <template #header>
        <h4>{{ userParams.id ? '更新用户信息' : '添加用户' }}</h4>
      </template>
      <template #default>
        <el-form :model="userParams" :rules="rules" ref="userForm">
          <el-form-item label="用户姓名" prop="username">
            <el-input
              placeholder="请输入用户姓名:"
              v-model="userParams.username"
            ></el-input>
          </el-form-item>
          <el-form-item label="用户昵称" prop="name">
            <el-input
              placeholder="请输入用户昵称"
              v-model="userParams.name"
            ></el-input>
          </el-form-item>
          <el-form-item
            label="用户密码"
            prop="password"
            v-if="userParams.id ? false : true"
          >
            <el-input
              placeholder="请输入用户密码"
              v-model="userParams.password"
            ></el-input>
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <div style="flex: auto">
          <el-button @click="cancelClick">取消</el-button>
          <el-button type="primary" @click="confirmClick">确定</el-button>
        </div>
      </template>
    </el-drawer>
    <!-- 给用户分配 -->
    <el-drawer v-model="drawer1">
      <template #header>
        <h4>职位(角色)分配</h4>
      </template>
      <template #default>
        <el-form>
          <el-form-item label="用户姓名">
            <el-input :disabled="true" v-model="userParams.username"></el-input>
          </el-form-item>
          <el-form-item label="职位列表">
            <el-checkbox
              v-model="checkAll"
              :indeterminate="isIndeterminate"
              @change="handleCheckAllChange"
            >
              全选
            </el-checkbox>
            <div style="width: 100%; height: 10px"></div>
            <el-checkbox-group
              v-model="userRole"
              @change="handleCheckedCitiesChange"
            >
              <el-checkbox
                v-for="(role, index) in allRole"
                :key="index"
                :label="role"
                :value="role"
              >
                {{ role.roleName }}
              </el-checkbox>
            </el-checkbox-group>
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <div style="flex: auto">
          <el-button @click="cancelRoleClick">取消</el-button>
          <el-button type="primary" @click="confirmRoleClick">确认</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
// 引人请求接口
import {
  reqUserInfo,
  reqAddOrUpdateUser,
  reqAllRole,
  reqSetUserRole,
  reqRemoveUser,
  reqSelectUser,
} from '@/api/acl/user/index'
// 引入接口返回的部分数据类型
import type {
  UserResponseData,
  UserList,
  User,
  AllRole,
  AllRoleResponseData,
  SetRoleData,
} from '@/api/acl/user/type'
// 引入仓库
import userMessageStore from '@/store/modules/user'
let userStore = userMessageStore()
// 获取setting仓库数据 获取main组件watch的属性 当仓库当中的flushed变化 使用v-if 和 nextTick实现main组件展示的路由组件的重新挂载
import useLayOutSettingStore from '@/store/modules/setting'
let settingStore = useLayOutSettingStore()
// 设置组件的名字
defineOptions({
  name: 'User',
})
// 生命周期钩子
onMounted(() => {
  getHasUser()
})

// 变量
let pageNo = ref<number>(1) //当前页面数
let pageSize = ref<number>(5) //当前页面大小
let total = ref<number>(200) //获取用户信息条数
let userArr = ref<UserList>([])
let drawer = ref<boolean>(false) //控制右侧抽屉隐藏和展示
let userParams = reactive<User>({
  //收集添加 | 修改的用户信息
  username: '',
  name: '',
  password: '',
})
let namecheck = ref<boolean>(false) //修改用户信息判断 是否为当前登录用户
let userForm = ref() //获取UserForm实例
let drawer1 = ref<boolean>(false) //角色分配抽屉是否展示
let selectUserList = ref<User[]>([])
let keyword = ref<string>('') //定义响应式数据:收集用户输入进来的关键字
// 多选框
const checkAll = ref(false) //是否全选
const isIndeterminate = ref(true) //显示不确定状态
const allRole = ref<AllRole>([])
const userRole = ref<any>([])
// 函数
// 关闭抽屉回调函数
const closeDrawer = () => {
  namecheck.value = false
}
// 获取展示的用户信息
const getHasUser = async () => {
  // 发生请求用户信息
  let result: UserResponseData = await reqUserInfo(
    pageNo.value,
    pageSize.value,
    keyword.value,
  )
  if (result.code == 200) {
    // 请求成功收集用户信息
    userArr.value = result.data.records
    total.value = result.data.total
  } else {
    // 请求失败提示用户重新加载
    ElMessage({
      type: 'error',
      message: '服务器出差了~重新试试吧~',
    })
  }
}
// 当页面展示条数发生变化回调的函数
const handler = () => {
  getHasUser()
}
// 抽屉点击取消回调
const cancelClick = () => {
  drawer.value = false
}
// 抽屉点击确认回调 保存按钮
const confirmClick = async () => {
  // 确保表单验证是否通过
  await userForm.value.validate()
  // 保存按钮:添加新的用户|更新已有的用户账号信息
  let result: any = await reqAddOrUpdateUser(userParams)
  if (result.code == 200) {
    // 请求成功
    // 关闭抽屉
    drawer.value = false
    // 重新获取用户信息
    if (!userParams.id) {
      // 如果是添加用户则展示回第一页
      pageNo.value = 1
    }
    // 展示提示信息
    ElMessage({
      type: 'success',
      message: userParams.id ? '更新用户信息成功' : '添加用户信息成功',
    })
    // 重新获取用户信息
    // getHasUser() 如果修改当前登录账号的用户信息 该用户的token就会失效 在刷新页面就会 调用路由拦截器 重新通过token获取用户信息 此时token过期返回登录页面
    if (namecheck.value == true) {
      ElMessage({
        type: 'warning',
        message: '修改了当前登录账号的信息, 将在3秒后返回登录页面',
      })
      namecheck.value = false
      setTimeout(() => {
        window.location.reload()
      }, 3000)
    } else {
      getHasUser()
    }
  } else {
    // 请求失败
    ElMessage({
      type: 'error',
      message: userParams.id
        ? '更新用户信息失败 T_T'
        : '添加用户信息失败了 T_T',
    })
  }
}
// 添加用户回调函数
const addUser = () => {
  // 在每次添加前需要重新的清空userParams当中的数据
  Object.assign(userParams, {
    // 清空id
    id: 0,
    username: '',
    name: '',
    password: '',
  })
  drawer.value = true
  //清除上一次的错误的提示信息
  nextTick(() => {
    userForm.value.clearValidate('username')
    userForm.value.clearValidate('name')
    userForm.value.clearValidate('password')
  })
}
// 更新用户信息回调函数
const updateUser = (row: User) => {
  drawer.value = true
  if (row.username == userStore.username) namecheck.value = true
  // 存储收集已有的账号信息
  Object.assign(userParams, row)
  // 清除上一次的错误提示信息
  nextTick(() => {
    userForm.value.clearValidate('username')
    userForm.value.clearValidate('name')
  })
}
// 分配角色抽屉 取消按钮回调
const cancelRoleClick = () => {
  // 收起抽屉
  drawer1.value = false
}
// 分配角色抽屉 确认按钮回调
const confirmRoleClick = async () => {
  // 收集参数
  let data: SetRoleData = {
    userId: userParams.id as number,
    roleIdList: userRole.value.map((item: { id: number }) => {
      return item.id as number
    }),
  }
  // 发送请求
  let result: any = await reqSetUserRole(data)
  if (result.code == 200) {
    ElMessage({
      type: 'success',
      message: '用户分配职位成功!',
    })
    // 重新获取数据
    getHasUser()
    // 关闭抽屉
    drawer1.value = false
  } else {
    ElMessage({
      type: 'error',
      message: '用户分配职位失败~稍后在试试吧',
    })
  }
}
// 分配角色按钮回调函数
const setRole = async (row: User) => {
  // 收集用户信息
  Object.assign(userParams, row)
  let result: AllRoleResponseData = await reqAllRole(userParams.id as number)
  if (result.code == 200) {
    // 请求成功
    // 收集职位数据
    allRole.value = result.data.allRolesList
    userRole.value = result.data.assignRoles
    // 打开分配职位抽屉
    drawer1.value = true
  } else {
    ElMessage({
      type: 'error',
      message: '服务器开小差了~稍后再试试吧~',
    })
  }
}
// 删除某一个用户
const deleteUser = async (userId: number) => {
  let result: any = await reqRemoveUser(userId)
  if (result.code == 200) {
    ElMessage({
      type: 'success',
      message: '删除用户成功',
    })
    // 判断当前展示的页面 数据条数 小于0 并且 pageNo > 1 的时候 让pageNo - 1
    if (pageNo.value > 1 && userArr.value.length < 1) pageNo.value -= 1
    // 重新获取数据
    getHasUser()
  } else {
    ElMessage({
      type: 'error',
      message: '删除失败请稍后再试',
    })
  }
}
// 批量删除用户
const deleteSelectUser = async () => {
  // 从勾选的用户数组,结构出ID数组 作为批量删除请求的参数
  let deleteUserIdList: any = selectUserList.value.map((item) => {
    return item.id
  })
  // 发送请求
  let result: any = await reqSelectUser(deleteUserIdList)
  if (result.code == 200) {
    ElMessage({
      type: 'success',
      message: '批量删除成功',
    })
    // 重新获取当前页面的数据
    // 判断当前展示的页面 数据条数 小于0 并且 pageNo > 1 的时候 让pageNo - 1
    if (pageNo.value > 1 && userArr.value.length < 1) pageNo.value -= 1
    // 重新获取数据
    getHasUser()
  } else {
    ElMessage({
      type: 'error',
      message: '批量删除失败了 , 稍后在试试吧',
    })
  }
}
// table勾选之后的回调函数
const selectChange = (checkDeleteUserList: any) => {
  // 收集勾选的用户数组
  selectUserList.value = checkDeleteUserList
}
//  搜索用户函数
const search = () => {
  // 获取搜索用户信息
  getHasUser()
  // 置空搜索框
  keyword.value = ''
}
// 重置函数
const refresh = () => {
  settingStore.flushed = !settingStore.flushed
}
// 校验规则对象
// 自定义校验规则
// 校验用户名字回调函数
const validatorUsername = (rule: any, value: any, callBack: any) => {
  // 用户名字 | 昵称的长度至少是五位
  if (value.trim().length >= 5) {
    callBack()
  } else {
    callBack(new Error('用户昵称至少是五位'))
  }
}
const validatorName = (rule: any, value: any, callBack: any) => {
  // 用户名字 | 昵称的长度至少是五位
  if (value.trim().length >= 5) {
    callBack()
  } else {
    callBack(new Error('用户昵称至少是五位'))
  }
}
const validatorPassword = (rule: any, value: any, callBack: any) => {
  // 用户名字 | 昵称的长度至少是五位
  if (value.trim().length >= 5) {
    callBack()
  } else {
    callBack(new Error('密码长度至少是五位'))
  }
}

const rules = {
  // 用户名字
  username: [
    {
      required: true,
      trigger: 'blur',
      validator: validatorUsername,
    },
  ],
  // 用户昵称
  name: [
    {
      required: true,
      trigger: 'blur',
      validator: validatorName,
    },
  ],
  // 用户密码
  password: [
    {
      required: true,
      trigger: 'blur',
      validator: validatorPassword,
    },
  ],
}

// 分配角色菜单
// 全选按钮回调
const handleCheckAllChange = (val: any): any => {
  userRole.value = val ? allRole.value : []
  isIndeterminate.value = false
}
// 底部选择回调
const handleCheckedCitiesChange = (value: any[]): any => {
  checkAll.value = value.length === allRole.value.length
  isIndeterminate.value = value.length !== allRole.value.length
}
</script>

<style scoped>
.search-form {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
